home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / CDTools / ClassAct / Examples / Layout / LayoutExample.c < prev    next >
C/C++ Source or Header  |  1997-07-09  |  15KB  |  515 lines

  1. /*************************************************************************
  2.  * ClassAct Comprehensive Demo Program
  3.  * Copyright © 1995 Osma Ahvenlampi
  4.  *
  5.  */
  6.  
  7. #include <exec/types.h>
  8. #include <exec/memory.h>
  9. #include <intuition/intuition.h>
  10. #include <intuition/gadgetclass.h>
  11. #include <intuition/icclass.h>
  12. #include <libraries/gadtools.h>
  13. #include <graphics/gfxbase.h>
  14. #include <graphics/text.h>
  15. #include <graphics/gfxmacros.h>
  16. #include <utility/tagitem.h>
  17. #include <workbench/startup.h>
  18. #include <workbench/workbench.h>
  19.  
  20. #include <proto/intuition.h>
  21. #include <proto/graphics.h>
  22. #include <proto/exec.h>
  23. #include <proto/dos.h>
  24. #include <proto/diskfont.h>
  25. #include <proto/utility.h>
  26. #include <proto/wb.h>
  27. #include <proto/icon.h>
  28.  
  29. #include <classact.h>
  30. #include <classact_lib.h>
  31. #include <clib/classact_lib_protos.h>
  32.  
  33. void __stdargs kprintf(const char *, ...);
  34.  
  35. /* a simple button */
  36. #define Button(a) ButtonObject, GA_Text, a, ButtonEnd
  37. #define DButton(a) ButtonObject, GA_Text, a, GA_Disabled, TRUE, ButtonEnd
  38.  
  39. /**************************************************************************
  40.  * Some label arrays for the gadgets in this demo.
  41.  */
  42.  
  43. static STRPTR objtypes[] = 
  44. {
  45.     "Exec",
  46.     "Image",
  47.     "Sound",
  48.     "Menu",
  49.     "Icon",
  50.     "Dock",
  51.     "Access",
  52.     NULL     
  53. };
  54.  
  55. static STRPTR objnames[] = 
  56. {
  57.     "ToolManager",
  58.     "ScreenMode",
  59.     "WBPattern",
  60.     NULL
  61. };
  62.  
  63. /*************************************************************************
  64.  * Gadget list
  65.  * This wouldn't be strictly necessary, but it's an easy way of keeping
  66.  * the gadget pointers for when we need to access the gadgets.
  67.  */
  68. typedef enum { G_ObjType = 1, G_ObjList, G_Top, G_Up, G_Down, G_Bottom,
  69.             G_Sort, G_New, G_Edit, G_Copy, G_Remove, G_Help, G_Save, G_Use,
  70.             G_Test, G_Cancel, G_MAX } GadgetIDs;
  71.  
  72. struct Gadget *GL[G_MAX+1];
  73.  
  74. /*************************************************************************
  75.  * ReadArgs
  76.  */
  77.  
  78. #define TEMPLATE "S=SIMPLEREFRESH/S,NC=NOCAREREFRESH/S,ND=NDEFER/S"
  79. LONG ARG[3];
  80. typedef enum { A_Simple, A_NoCare, A_NoDefer } Args;
  81.  
  82. /*************************************************************************
  83.  * App message hook.
  84.  * Workbench App messages can be caught with a callback hook such as this.
  85.  * We'll not worry about the app message type in this hook. Objects dropped
  86.  * on the window or on the icon (while iconified) will be added to the 
  87.  * listview.
  88.  */
  89.  
  90. void __asm __saveds AppMsgFunc(    register __a0 struct Hook *Hook,
  91.                                 register __a2 Object *Window,
  92.                                 register __a1 struct AppMessage *Msg )
  93. {
  94.     struct Window *Win;
  95.     struct WBArg *arg = Msg->am_ArgList;
  96.     LONG i = Msg->am_NumArgs;
  97.     struct List *l = Hook->h_Data;
  98.     struct Node *n;
  99.     UBYTE name[256];
  100.     
  101.     GetAttr( WINDOW_Window, Window, (ULONG *)&Win );
  102.  
  103.     /* Detach the list for modifications.
  104.      */
  105.     SetGadgetAttrs( GL[G_ObjList], Win, NULL, LISTBROWSER_Labels, ~0, TAG_END );
  106.         
  107.     while (i--)
  108.     {
  109.         /* Add the name of the icon to the listview. ListBrowser can copy the
  110.          * text into an internal buffer and thus let us not worry about the
  111.          * pointer validity.
  112.          */
  113.         
  114.         NameFromLock( arg->wa_Lock, name, sizeof(name) );
  115.         AddPart( name, arg->wa_Name, sizeof(name) );
  116.         
  117.         if (n = AllocListBrowserNode( 1, LBNCA_CopyText, TRUE, LBNCA_Text, name, TAG_END ))
  118.             AddTail( l, n );
  119.             
  120.         arg++;
  121.     }
  122.     
  123.     /* Reattach the list */
  124.     SetGadgetAttrs( GL[G_ObjList], Win, NULL, LISTBROWSER_Labels, l, TAG_END );
  125. }
  126.  
  127. /*************************************************************************
  128.  * Main Program
  129.  */
  130. int 
  131. main(void)
  132. {
  133.     struct List *objlist; 
  134.     struct List *typelist; 
  135.     struct RDArgs *args;
  136.     struct MsgPort *appport;
  137.  
  138.     if (!ButtonBase) /* force it open */
  139.         return 30;
  140.         
  141.     if (!(args = ReadArgs(TEMPLATE, ARG, NULL)))
  142.         return 20;
  143.         
  144.     Printf("%seferred %s refresh %s\n", ARG[A_NoDefer] ? "Non-d" : "D", ARG[A_Simple] ? "Simple" : "Smart", ARG[A_NoCare] ? "(NoCare)" : "");
  145.  
  146.     objlist = BrowserNodesA( objnames );
  147.     typelist = ChooserLabelsA( objtypes );
  148.  
  149.     /* By providing a message port you enable windowclass to handle iconification
  150.      * and appwindows. This port can shared by all the windows of your application.
  151.      */
  152.     appport = CreateMsgPort();
  153.  
  154.     if (objlist && typelist && appport)
  155.     {
  156.         struct Gadget *MainLayout;
  157.         Object *Window;
  158.         
  159.         struct Hook apphook;
  160.         apphook.h_Entry = (ULONG (* )())AppMsgFunc;
  161.         apphook.h_SubEntry = NULL;
  162.         apphook.h_Data = objlist;
  163.         
  164.         /* Create a Window object with a Layout. When Window is asked to open itself,
  165.          * it will calculate how much space the Layout needs and size itself accordingly.
  166.          */
  167.     
  168.         Window = WindowObject,
  169.                 
  170.                 /* these tags describe the window 
  171.                  */
  172.         
  173.                 WA_IDCMP, IDCMP_RAWKEY,
  174.                 WA_Top, 20,
  175.                 WA_Left, 20,
  176.                 WA_SizeGadget, TRUE,
  177.                 WA_DepthGadget, TRUE,
  178.                 WA_DragBar, TRUE,
  179.                 WA_CloseGadget, TRUE,
  180.                 WA_Activate, TRUE,
  181.                 
  182.                 /* About window refreshes:
  183.                  * Because WindowClass and LayoutClass can, when used together, change the
  184.                  * normal Intuition practise of refreshing gadgets in the input.device context,
  185.                  * some rules about the refresh system change.
  186.                  * Deferred refresh works in both smart and simple refresh windows, but
  187.                  * if nocarerefresh is used, Intuition does not retain the damage regions
  188.                  * and any window damage will force the whole window to be refreshed.
  189.                  * This demo allows you to try combinations of refresh types.
  190.                  * In the normal case you can ignore this and let WindowClass and the user
  191.                  * decide what kind of refreshes they want. Nocare refresh can be
  192.                  * combined with smart refresh to provide a fast, but somewhat more memory
  193.                  * hungry refresh method. Simple refresh can save some memory but it's
  194.                  * slower.
  195.                  */
  196.                 
  197.                 WA_SimpleRefresh, ARG[A_Simple],
  198.                 WA_NoCareRefresh, ARG[A_NoCare],    
  199.                 WA_SmartRefresh, !ARG[A_Simple],
  200.                 
  201.                 WA_Title, "ClassAct layout.gadget Example (ToolManager preferences mockup)",
  202.                 WA_ScreenTitle, "ClassAct Copyright 1995 Phantom Development LLC.",
  203.                 
  204.                 /* Turn on gadget help in the window 
  205.                  */
  206.                 
  207.                 WINDOW_GadgetHelp, TRUE,
  208.                 
  209.                 /* Add an iconification gadget. If you have this, you must listen to
  210.                  * WMHI_ICONIFY.
  211.                  */
  212.                  
  213.                 WINDOW_IconifyGadget, TRUE,
  214.                 
  215.                 /* This message port lets windowclass handle the icon and appwindow.
  216.                  */
  217.                  
  218.                 WINDOW_AppPort, appport,
  219.                 WINDOW_AppWindow, TRUE,
  220.                 WINDOW_AppMsgHook, &apphook,
  221.                 
  222.                 /* The windowclass will automatically free the DiskObject used when
  223.                  * iconifying the window. If you do not provide a valid DiskObject,
  224.                  * windowclass will try to use env:sys/def_window.info or the default
  225.                  * project icon.
  226.                  */
  227.                 
  228.                 WINDOW_Icon, GetDiskObject( "LayoutExample" ),
  229.                 WINDOW_IconTitle, "ClassAct Example",
  230.                 
  231.                 /* Below is the layout of the window 
  232.                  */
  233.                 
  234.                 WINDOW_ParentGroup,    MainLayout = VGroupObject,
  235.                     LAYOUT_SpaceOuter, TRUE,
  236.                     LAYOUT_BevelStyle, BVS_THIN,
  237.                     
  238.                     /* this tag instructs layout.gadget to defer GM_LAYOUT and GM_RENDER and ask
  239.                      * the windowclass to do them. This lessens the load on input.device 
  240.                      */
  241.                     LAYOUT_DeferLayout, !ARG[A_NoDefer],
  242.  
  243.                     /* A 1-of-n chooser using the labels list we made from the label array earlier 
  244.                      */
  245.  
  246.                     StartMember, GL[G_ObjType] = ChooserObject,
  247.                         CHOOSER_Labels, typelist,
  248.                     EndMember,
  249.                     MemberLabel("_Object Type"),
  250.                     
  251.                     /* Objects can be given arbitary weights within groups, and layout.gadget
  252.                      * will distribute space relative to the total weight of the group.
  253.                      * Here we set the button column to 0 weight which means minimum space.
  254.                      * Thus the listview gets all available extra space.
  255.                      */
  256.                     
  257.                     StartHGroup, BAligned,
  258.                         StartMember, GL[G_ObjList] = ListBrowserObject,
  259.                             LISTBROWSER_Labels, objlist,
  260.                             LISTBROWSER_ShowSelected, TRUE,
  261.                         EndMember,
  262.                         
  263.                         StartVGroup,
  264.                             StartMember, GL[G_Top] = DButton("Top"),
  265.                             StartMember, GL[G_Up] = DButton("Up"),
  266.                             StartMember, GL[G_Down] = DButton("Down"),
  267.                             StartMember, GL[G_Bottom] = DButton("Bottom"),
  268.                             StartMember, GL[G_Sort] = Button("So_rt"),
  269.                         EndGroup,
  270.                         CHILD_WeightedWidth, 0,
  271.                         
  272.                         /* One way to keep the buttons constant size is to set the
  273.                          * group to stay at minimum size with a weight of 0. We could
  274.                          * also set the weight of each of the buttons to 0. That way
  275.                          * extra space would be distributed between the buttons
  276.                          * instead of all below. This looks better.
  277.                          */
  278.                         
  279.                         CHILD_WeightedHeight, 0,
  280.                     EndGroup,
  281.                     
  282.                     /* two rows of buttons. EvenSized instructs layout.gadget that it
  283.                      * should make sure the minimum size of each matches, so that we
  284.                      * get four neat columns.
  285.                      * Again the weight is set to 0. When the window is resized, all
  286.                      * space is given to the listview.
  287.                      */
  288.                     
  289.                     StartHGroup, EvenSized,
  290.                         StartMember, GL[G_New] = Button("_New..."),
  291.                         StartMember, GL[G_Edit] = DButton("_Edit..."),
  292.                         StartMember, GL[G_Copy] = DButton("Co_py"),
  293.                         StartMember, GL[G_Remove] = DButton("Remove"),
  294.                     EndGroup,
  295.                     CHILD_WeightedHeight, 0,
  296.                     
  297.                     StartHGroup, EvenSized,
  298.                         StartMember, GL[G_Save] = Button("_Save"),
  299.                         StartMember, GL[G_Use] = Button("_Use"),
  300.                         StartMember, GL[G_Test] = Button("_Test"),
  301.                         StartMember, GL[G_Cancel] = Button("_Cancel"),
  302.                     EndGroup,
  303.                     CHILD_WeightedHeight, 0,
  304.                     
  305.                     StartMember, GL[G_Help] = ButtonObject,
  306.                         GA_ReadOnly, TRUE,
  307.                         GA_Text, "Welcome to ClassAct demo!",
  308.                     EndMember,
  309.                     CHILD_WeightedHeight, 0,
  310.                 EndGroup,
  311.             EndWindow;
  312.     
  313.         if (Window)
  314.         {
  315.             /* Window pointer cache.
  316.              */
  317.         
  318.             struct Window *Win;
  319.         
  320.             /* Finish the gadgetarray initialisation. Set gadget IDs and release verify. 
  321.              * This is one way of avoiding boring repetition in the layout description
  322.              * taglist itself.
  323.              */
  324.             
  325.             {
  326.                 LONG i = 1;
  327.                 do SetAttrs(GL[i], GA_ID, i, GA_RelVerify, TRUE, TAG_END);
  328.                 while (GL[++i]);
  329.             }
  330.             
  331.             if (Win = CA_OpenWindow( Window ))
  332.             {
  333.                 ULONG wsig, asig = 1L << appport->mp_SigBit;
  334.                 BOOL done = FALSE;
  335.                 
  336.                 /* Now that the window has been opened, we can get the signal mask
  337.                  * of its user port. If the program supported iconification and didn't
  338.                  * use a shared IDCMP port between all windows, this signal bit
  339.                  * would have to be re-queried before each Wait().
  340.                  */
  341.                 
  342.                 GetAttr( WINDOW_SigMask, Window, &wsig );
  343.     
  344.                 while (done == FALSE)
  345.                 {
  346.                     ULONG sig = Wait(wsig | asig | SIGBREAKF_CTRL_C);
  347.                     ULONG result;
  348.                     UWORD code;
  349.  
  350.                     if (sig & (wsig | asig))
  351.                     {
  352.                         /* Messages waiting at the window's IDCMP port. Loop at WM_HANDLEINPUT
  353.                          * until all have been processed.
  354.                          */
  355.                     
  356.                         while ((result = CA_HandleInput(Window,&code)) != WMHI_LASTMSG)
  357.                         {
  358.                             /* The return code of this method is two-part. The upper word describes the
  359.                              * class of the message (gadgetup, menupick, closewindow, iconify, etc),
  360.                              * and the lower word is a class-defined ID, currently in use in the
  361.                              * gadgetup and menupick return codes.
  362.                              * Switch on the class, then on the ID.
  363.                              */
  364.                         
  365.                             switch(result & WMHI_CLASSMASK)
  366.                             {
  367.                             case WMHI_GADGETUP:
  368.                             
  369.                                 /* OK, got a gadgetup from something. Lets find out what the something is.
  370.                                  * The code WORD to which a pointer was passed to WM_HANDLEINPUT has been
  371.                                  * set to the Code value from the IDCMP_GADGETUP, in case we need it.
  372.                                  */
  373.                             
  374.                                 switch(result & WMHI_GADGETMASK)
  375.                                 {
  376.                                 case G_ObjList:
  377.                                     /* User clicked on the listview 
  378.                                      */
  379.                                     {
  380.                                         static ULONG ids[] = { G_Top, G_Up, G_Down, G_Bottom, G_Edit, G_Copy, G_Remove, 0 };
  381.                                         ULONG i, dis = FALSE;
  382.                                         
  383.                                         if (code == ~0) /* no node was selected */
  384.                                             dis = TRUE;
  385.                                         
  386.                                         for ( i = 0 ; ids[i] ; i++ )
  387.                                         {
  388.                                             SetGadgetAttrs( GL[ids[i]], Win, NULL, GA_Disabled, dis, TAG_END );
  389.                                             RefreshGList( GL[ids[i]], Win, NULL, 1 );
  390.                                         }
  391.                                         
  392.                                         break;
  393.                                     }
  394.                                 }
  395.                                 break;
  396.                                 
  397.                             case WMHI_GADGETHELP:
  398.                                 {
  399.                                     STRPTR helptext;
  400.                                     
  401.                                     /* A gadget help message informs the application about the gadget
  402.                                      * under the mouse pointer. The code WORD is set to the value the
  403.                                      * gadget returned. Result code contains the ID of the gadget, 
  404.                                      * or NULL (not in the window) or WMHI_GADGETMASK (not over a gadget).
  405.                                      */
  406.                                 
  407.                                     switch(result & WMHI_GADGETMASK)
  408.                                     {
  409.                                     case G_ObjType:
  410.                                         helptext = "Choose object type";
  411.                                         break;
  412.                                     case G_ObjList:
  413.                                         helptext = "Choose object to modify";
  414.                                         break;
  415.                                     case G_Top:
  416.                                         helptext = "Move object to top";
  417.                                         break;
  418.                                     case G_Up:
  419.                                         helptext = "Move object upwards";
  420.                                         break;
  421.                                     case G_Down:
  422.                                         helptext = "Move object downwards";
  423.                                         break;
  424.                                     case G_Bottom:
  425.                                         helptext = "Move object to bottom";
  426.                                         break;
  427.                                     case G_Sort:
  428.                                         helptext = "Sort object list";
  429.                                         break;
  430.                                     case G_New:
  431.                                         helptext = "Create new object";
  432.                                         break;
  433.                                     case G_Edit:
  434.                                         helptext = "Edit object";
  435.                                         break;
  436.                                     case G_Copy:
  437.                                         helptext = "Make a new copy of object";
  438.                                         break;
  439.                                     case G_Remove:
  440.                                         helptext = "Delete the object";
  441.                                         break;
  442.                                     case G_Help:
  443.                                         helptext = "Hey there ;)";
  444.                                         break;
  445.                                     case G_Save:
  446.                                         helptext = "Save settings";
  447.                                         break;
  448.                                     case G_Use:
  449.                                         helptext = "Use these settings";
  450.                                         break;
  451.                                     case G_Test:
  452.                                         helptext = "Test these settings";
  453.                                         break;
  454.                                     case G_Cancel:
  455.                                         helptext = "Cancel changes";
  456.                                         break;
  457.                                     default:
  458.                                         helptext = "";
  459.                                         break;
  460.                                     }
  461.                                     if (SetGadgetAttrs( GL[G_Help], Win, NULL, GA_Text, helptext, TAG_END ))
  462.                                         RefreshGList(GL[G_Help], Win, NULL, 1);
  463.                                 }
  464.                                 break;
  465.  
  466.                             case WMHI_CLOSEWINDOW:
  467.                                 /* The window close gadget was hit. Time to die...
  468.                                  */
  469.                                 done = TRUE;
  470.                                 break;
  471.                                 
  472.                             case WMHI_ICONIFY:
  473.                                 /* Window requests that it be iconified. Handle this event as
  474.                                  * soon as possible. The window is not iconified automatically to
  475.                                  * give you a chance to make note that the window pointer will be 
  476.                                  * invalid before the window closes. It also allows you to free
  477.                                  * resources only needed when the window is open, if you wish to.
  478.                                  */
  479.                                 if (CA_Iconify( Window ))
  480.                                     Win = NULL;
  481.                                 break;
  482.                                  
  483.                             case WMHI_UNICONIFY:
  484.                                 /* The window should be reopened. If you had free'd something
  485.                                  * on iconify, now is the time to re-allocate it, before calling
  486.                                  * CA_OpenWindow.
  487.                                  */
  488.                                 Win = CA_OpenWindow( Window );
  489.                                 break;
  490.                             }
  491.                         }
  492.                     }
  493.                     else if (sig & SIGBREAKF_CTRL_C)
  494.                     {
  495.                         done = TRUE;
  496.                     }
  497.                 }
  498.                 /* Close the window and dispose of all attached gadgets 
  499.                  */
  500.                 DisposeObject( Window );
  501.             }
  502.         }
  503.     }
  504.     
  505.     if (appport)
  506.         DeleteMsgPort(appport);
  507.     
  508.     /* NULL is valid input for these helper functions, so no need to check.
  509.      */
  510.     FreeChooserLabels( typelist );
  511.     FreeBrowserNodes( objlist );
  512.     
  513.     FreeArgs(args);
  514. }
  515.